package com.geek.game.manager.agent.service.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.validation.groups.Default;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fasterxml.jackson.core.JsonParser;
import com.geek.game.manager.agent.base.Constants;
import com.geek.game.manager.agent.base.mvc.RequestMethod;
import com.geek.game.manager.agent.base.mvc.RequestModel;
import com.geek.game.manager.agent.base.mvc.WorkException;
import com.geek.game.manager.agent.base.utils.DateTimeUtil;
import com.geek.game.manager.agent.base.utils.HttpUtil;
import com.geek.game.manager.agent.base.utils.HttpUtils;
import com.geek.game.manager.agent.base.utils.JacksonUtil;
import com.geek.game.manager.agent.base.utils.TransSerialNumTool;
import com.geek.game.manager.agent.model.AgentSaleRecord;
import com.geek.game.manager.agent.model.Club;
import com.geek.game.manager.agent.model.ClubPlayerMapping;
import com.geek.game.manager.agent.model.CoinRecordModel;
import com.geek.game.manager.agent.model.ConsumerRecord;
import com.geek.game.manager.agent.model.DayReport;
import com.geek.game.manager.agent.model.Manager;
import com.geek.game.manager.agent.model.Player;
import com.geek.game.manager.agent.service.ClubService;

import ydh.cicada.dao.JdbcDao;
import ydh.cicada.dao.Page;
import ydh.cicada.query.QueryObject;
import ydh.cicada.query.Updater;


@Service("clubService")
@Transactional(rollbackFor={RuntimeException.class,WorkException.class})
public class ClubServiceImpl implements ClubService {

	@Autowired
	private JdbcDao dao;
	
	@Override
	public Integer insertClub(Club club) {
		dao.insert(club);
		return 1;
	}

	@Override
	public Club selectClubById(String clubId) {
		return dao.load(Club.class, Integer.valueOf(clubId));
	}

	@Override
	public Club selectClubByPlayerId(String playerId) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Integer updateClubInfo(Club club) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Integer insertClubMapping(ClubPlayerMapping mapping, Club club) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ClubPlayerMapping selectByPlayerId(String playerId) {
		
		return QueryObject.select(ClubPlayerMapping.class)
				.cond("disabled").equ(false)
				.cond("player_id").equ(playerId)
				.firstResult(dao);
	}

	@Override
	public List<Club> selectClubListByManagerId(String managerId) {
		return QueryObject.select(Club.class)
				.cond("club_manager_id").equ(managerId)
				.cond("disabled").notEqu(true)
				.list(dao);
	}

	@Override
	public List<ClubPlayerMapping> selectMembers(String clubId,String searchKey,Map<String,Object> map) {
		
		QueryObject<ClubPlayerMapping> query=QueryObject.select("c.*,p.nick_name playerName,p.diamond playerDiamond",ClubPlayerMapping.class)
				.from("club_player_mapping c"
						+ " left join player p on(p.id=c.player_id)")
					.cond("c.club_id").equ(clubId)
					.cond("c.disabled").notEqu(true);
		query.page(Long.valueOf(map.get("page").toString()));
		query.pageSize(Integer.valueOf(map.get("rows").toString()));
		if(StringUtils.isNotBlank(searchKey)){
			query.condition("p.id like ? or p.nick_name like ?", new Object[]{"%"+searchKey+"%","%"+searchKey+"%"});
		}
		Page<ClubPlayerMapping> page=dao.find(query);
		map.put("total", page.getTotalSize());
		return page.getData();
	}

	@Override
	public int agentSendOut(Integer playerId, Manager manager, Integer diamond,String clubId) throws WorkException {
		Player player=dao.load(Player.class, playerId);
		if(player!=null){
			Integer totalCheckDiamond=player.getDiamond()+manager.getAgentCoin();
			Integer baseCoin=new Integer(manager.getAgentCoin());
			player.setDiamond(player.getDiamond()+diamond);
			manager.setAgentCoin(manager.getAgentCoin()-diamond);
			try {
				if(totalCheckDiamond==player.getDiamond()+manager.getAgentCoin()){
					//dao.update(player);
					dao.update(manager);
					recordAgentSale(player.getId(),manager.getId(),diamond,Constants.PLAYER_ROLE);
					if(Constants.envFlag){
						return postJson(playerId.toString(),diamond);
					}
					return 1;
				}else{
					throw new Exception();
				}
			} catch (Exception e) {
				manager.setAgentCoin(baseCoin);//回滚钻石
				throw new WorkException("钻石售卖出错"+e.getMessage());
			}
		}
		return 0;
	}

	/**
	 * 插入销售记录
	 * @param playerId	玩家id
	 * @param managerId	管理员Id
	 * @param saleNumbers	销售数量(可为负数?)
	 * @param role	角色
	 * @return
	 */
	private int recordAgentSale(String playerId,String managerId,Integer saleNumbers,final Integer role){
		CoinRecordModel record2=new CoinRecordModel();
		record2.setRecordId(TransSerialNumTool.createSerialNum());
		record2.setAmount(0);
		record2.setMahjongCoin(saleNumbers);
		record2.setPlayerRole(role);
		record2.setManagerId(managerId);
		record2.setPlayerId(playerId);
		record2.setRecordTime(new Date());
		dao.insert(record2);
		return 1;
	}

	@Override
	public int changeRemarks(Integer mappingId, String comment) {
		ClubPlayerMapping mapping=dao.load(ClubPlayerMapping.class, mappingId);
		if(mapping!=null){
			return Updater.update(ClubPlayerMapping.class)
			.put("remarks", comment)
			.put("modify_time", new Date())
			.cond("id").equ(mappingId)
			.exec(dao);
		}
		return 0;
	}

	@Override
	public int kickOutClub(Integer clubId, Integer playerId) {
		if(Updater.update(Club.class).minus("club_size", 1)
				.cond("club_id").equ(clubId)
				.exec(dao)<1){
			return 0;
		}
		return Updater.update(ClubPlayerMapping.class).put("disabled", true)//留下数据痕迹，保存记录
				.put("modify_time", new Date())//修改时间
				.cond("club_id").equ(clubId)
				.cond("player_id").equ(playerId)
				.exec(dao);
	}

	@Override
	public int editDefDiamond(Integer clubId, Integer diamond) throws WorkException {
		
		Club club=dao.load(Club.class, clubId);
		if(club!=null){
//			Integer oldDefV=club.getClubAdvanceDiamond();
			Updater.update(ClubPlayerMapping.class)
			.put("advance_diamond", diamond)
//			.condition("advance_diamond=? and club_id=?", new Object[]{oldDefV,clubId})
			.cond("advance_diamond").equ(club.getClubAdvanceDiamond())
			.cond("club_id").equ(clubId)
			.exec(dao);
			if(Updater.update(Club.class)
						.put("club_advance_diamond", diamond)
						.cond("club_id").equ(clubId)
						.exec(dao)>0){
				return 1;
			}
			throw new WorkException("修改默认额度出错！");
		}
		return 0;
	}

	@Override
	public int closeOrOpenPermit(String mappingId, Integer type) {
		return Updater.update(ClubPlayerMapping.class)
				.put("permit", type)
				.cond("id").equ(mappingId)
				.exec(dao);
	}

	@Override
	public int clearArrearage(String mappingId) {
		return Updater.update(ClubPlayerMapping.class)
				.put("arrearage", 0)
				.cond("id").equ(mappingId)
				.exec(dao);
	}

	@Override
	public int changePassword(String newPassword, String managerId) {
		return Updater.update(Manager.class).put("password", newPassword).cond("user_id").equ(managerId).exec(dao);
	}

	@Override
	public List<ConsumerRecord> getRecordList(String clubId, String searchKey,Map map) {
		QueryObject<ConsumerRecord> query=QueryObject.select("c.*,p.nick_name playerName",ConsumerRecord.class).from("consumer_record c left join player p on(p.id=c.consumer_id)"
				+ " left join club_player_mapping m ON(m.player_id=p.id and m.disabled=0)")
				.cond("m.club_id").equ(clubId);
		if(StringUtils.isNotBlank(searchKey)){
			query.condition("p.nick_name like ? or p.id=?", new Object[]{"%"+searchKey+"%",searchKey});
		}
		map.put("total", dao.count(query));
		query.page(Long.valueOf(map.get("page").toString()));
		query.pageSize(Integer.valueOf(map.get("rows").toString()));
		Page<ConsumerRecord> page=dao.find(query);
		return page.getData();
	}
	
	private int postJson(String playerId,Integer diamond) throws IOException{
		List<String> args=new ArrayList<String>();
		RequestModel requestModel=new RequestModel();
        requestModel.setCmd(RequestMethod.addDiamond);
        args.add(playerId);
        args.add(diamond.toString());
        requestModel.setArgs(args);
        int resultUpdate = 0;
        String paraStr= JacksonUtil.getJsonFromObject(requestModel);
        String result= HttpUtil.PostWithJson(paraStr);
        System.err.println(result);
        Map jsonResult=JacksonUtil.getObjectFromJson(result, Map.class);
        resultUpdate=Integer.parseInt(String.valueOf(jsonResult.get("res")));
        if(resultUpdate>0){
        	
        	System.out.println("加钻成功!玩家"+playerId+"增加钻石额度"+diamond);
        }else{
        	System.err.println("加钻失败，金额："+diamond);
        	new WorkException("加钻失败，金额："+diamond+"玩家:"+playerId);
        }
		return resultUpdate;
	}

	@Override
	public List<DayReport> getReports(Map map) {
		String managerId=(String) map.get("managerId");
		QueryObject<DayReport> query=QueryObject.select("time, sum(rounds) rounds, sum(sale) sale, sum(money) consume",DayReport.class)
				.from("(SELECT DATE_FORMAT(t.record_time, '%y/%m/%d') time, 0 AS rounds, sum(t.mahjong_coin) AS sale, 0 AS money "
						+ " FROM t_recharge_record t "
						+ " WHERE t.user_id=?"
						+ " GROUP BY time "
						+ " UNION"
						+ " SELECT DATE_FORMAT(c.consume_time, '%y/%m/%d') time, count(1) AS rounds, 0 AS sale, sum(c.order_money) AS money "
						+ " FROM consumer_record c "
						+ " WHERE c.cost_id = ? GROUP BY time) total")
				.condition("1=1", new Object[]{managerId,managerId})
				.groupBy("time")
				.desc("time");
		query.page(Long.valueOf(map.get("page").toString()));
		query.pageSize(Integer.valueOf(map.get("rows").toString()));
		Page<DayReport> page=dao.find(query);
		map.put("total", page.getTotalSize());
		return page.getData();
	}

	@Override
	public List<AgentSaleRecord> getSaleRecord(Map map) {
		String managerId=(String) map.get("managerId");
		QueryObject<AgentSaleRecord> query=QueryObject.select("t.id,t.player_id playerId,t.mahjong_coin saleNumbers,t.record_time createTime,"
				+ " (CASE WHEN t.player_role = 1 THEN ( SELECT p.nick_name FROM player p WHERE p.id = t.player_id ) "
				+ " ELSE ( SELECT m.user_name FROM t_manager m WHERE m.user_id = t.player_id ) end)playerName",AgentSaleRecord.class);
		query.from("t_recharge_record t");
		if(map.get("startDate")!=null && StringUtils.isNotBlank(map.get("startDate").toString())){
			query.condition("t.user_id=?"
					+ "and t.record_time>=str_to_date(?,'%Y-%m-%d') and t.record_time<=DATE_ADD(str_to_date(?,'%Y-%m-%d'),INTERVAL 1 DAY)", new Object[]{managerId,map.get("startDate"),map.get("endDate")});
		}else{
			query.condition("t.user_id=?", new Object[]{managerId});
		}
		query.page(Long.valueOf(map.get("page").toString()));
		query.pageSize(Integer.valueOf(map.get("rows").toString()));
		query.desc("t.record_time");
		Page<AgentSaleRecord> page=dao.find(query);
		map.put("total", page.getTotalSize());
		return page.getData();
	}

	@Override
	public List<CoinRecordModel> getBuyRecord(Map map) {
		String managerId=(String) map.get("managerId");
		QueryObject<CoinRecordModel> query=QueryObject.select("*,id recordId",CoinRecordModel.class);
		if (map.get("startDate")!=null && StringUtils.isNotBlank(map.get("startDate").toString())) {
			query.condition("player_id=? and player_role=? and record_time>=str_to_date(?,'%Y-%m-%d') and record_time<=DATE_ADD(str_to_date(?,'%Y-%m-%d'),INTERVAL 1 DAY)", new Object[]{managerId,Constants.MANAGER_ROLE,map.get("startDate"),map.get("endDate")});
		}else{
			query.condition("player_id=? and player_role=?", new Object[]{managerId,Constants.MANAGER_ROLE});
		}
		if(map.get("page")!=null && map.get("rows")!=null){
			query.page(Long.valueOf(map.get("page").toString()));
			query.pageSize(Integer.valueOf(map.get("rows").toString()));
		}
		query.desc("record_time");
		Page<CoinRecordModel> page=dao.find(query);
		map.put("total", page.getTotalSize());
		return page.getData();
	}

	@Override
	public Player searchPlayer(Map map) {
		String playerId=(String) map.get("playerId");
		Player p=dao.load(Player.class, playerId);
		return p;
	}

	@Override
	public int checkPhone(Map map) {
		String phone=(String) map.get("phone");
		return QueryObject.select("count(1)",Integer.class).from("t_manager")
				.cond("user_account").equ(phone)
				.uniqueResult(dao);
	}
	//创建二级代理
	@Override
	public int insertSubAgent(Map map) throws Exception {
		
		Updater<Manager> updeter=Updater.update(Manager.class).minus("agent_coin", Constants.SUBAGENT_DEFAULT_DIAMOND)
				.cond("user_id").equ((String) map.get("parentManagerId"))
				.cond("agent_coin").gtEqu(Constants.SUBAGENT_DEFAULT_DIAMOND);//
		int factRow=updeter.exec(dao);
		if(factRow<1){
			return -1;//钻石的不足
		}
		Player p=dao.load(Player.class, map.get("playerId").toString());
		Manager m=new Manager();
		Date now=new Date();
		m.setPlayerId(p.getId());
		m.setCreateTime(now);
		m.setUpdateTime(now);
		m.setParentManager((String) map.get("parentManagerId"));
		m.setPlayerId((String) map.get("playerId"));
		m.setUserAccount((String) map.get("account"));
		m.setPassword(Constants.DEFAULT_PWD);
		m.setManagerType(Constants.MANAGER_TYPE_SUBAGENT);
		m.setAgentCoin(Constants.SUBAGENT_DEFAULT_DIAMOND);
		m.setDelTag("0");
		m.setUserName(p.getNickName());
		dao.insert(m);
		int affectRow=recordAgentSale(m.getId(),map.get("parentManagerId").toString(),Constants.SUBAGENT_DEFAULT_DIAMOND,Constants.MANAGER_ROLE);
		if(affectRow<1){
			throw new WorkException("添加充值记录出错!");//增加记录出错,回滚数据
		}
		Random random = new Random();
        int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;// 获取5位随机数
        while(selectClubId(String.valueOf(rannum))>0){
        	rannum=(int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;
        }
        Club club=new Club();
        club.setClubId(rannum);
        club.setClubName((String) map.get("clubName"));
        club.setClubManagerId(Integer.valueOf(m.getId()));
        club.setClubSize(1);
        club.setClubAdvanceDiamond(Constants.CLUB_DEFAULT_DIAMOND);
        club.setCreateTime(now);
        club.setModifyTime(now);
        club.setClubNotice("子代理");
        dao.insert(club);
        
        ClubPlayerMapping mapping=new ClubPlayerMapping();
        mapping.setAdvanceDiamond(Constants.CLUB_DEFAULT_DIAMOND);
        mapping.setCreateTime(new Date());
        mapping.setModifyTime(new Date());
        mapping.setClubId(club.getClubId());
        mapping.setPlayerId(Integer.valueOf(p.getId()));
        mapping.setArrearage(0);
        dao.insert(mapping);
		return 1;
	}
	
	private int selectClubId(String number){
		return QueryObject.select("count(1)",Integer.class)
				.from("club")
				.cond("club_id").equ(number)
				.uniqueResult(dao);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Manager> subManager(@SuppressWarnings("rawtypes") Map param) {
		QueryObject<Manager> query=QueryObject.select(Manager.class)
				.from("t_manager t")
				.cond("t.parent_manager").equ(param.get("parentManagerId"))
				.cond("t.deltag").equ(Constants.PLAYER_USED);
		query.page(Long.valueOf(param.get("offset").toString()));
		query.pageSize(Integer.valueOf(param.get("limit").toString()));
		Page<Manager> page=dao.find(query);
		param.put("total", page.getTotalSize());
		param.put("rows", page.getData());
		return page.getData();
	}
	/**
	 * 一级代理卖出钻石给二级
	 */
	@Override
	public int saleToSubAgent(String subAgentId, Integer diamond, String managerId) throws WorkException {
		Updater<Manager> updater=Updater.update(Manager.class).minus("agent_coin", diamond)
				.cond("user_id").equ(managerId);
		int affectRow=updater.exec(dao);
		if(affectRow>0){
			affectRow=0;
			affectRow=Updater.update(Manager.class).add("agent_coin", diamond)
					.cond("user_id").equ(subAgentId).exec(dao);
			if(affectRow>0){
				affectRow=0;
				affectRow=recordAgentSale(subAgentId,managerId,diamond,Constants.MANAGER_ROLE);
			}
			if(affectRow<1){
				throw new WorkException("插入记录失败!请联系管理员");
			}
		}
		return affectRow;
	}
}
